// EnvironmentMetricsServiceImpl.java
package com.example.smartgreenhouse.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.smartgreenhouse.entity.*;
import com.example.smartgreenhouse.dto.*;
import com.example.smartgreenhouse.exception.BusinessException;
import com.example.smartgreenhouse.mapper.*;
import com.example.smartgreenhouse.service.EnvironmentMetricsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class EnvironmentMetricsServiceImpl implements EnvironmentMetricsService {

    // 各指标Mapper注入
    private final AirHumidityMapper airHumidityMapper;
    private final AirTemperatureMapper airTemperatureMapper;
    private final LightIntensityMapper lightIntensityMapper;
    private final SoilMoistureMapper soilMoistureMapper;
    private final EnvironmentMetricsMapper environmentMetricsMapper;


    // 指标类型校验集合
    private static final Set<String> VALID_METRICS =
            Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
                    "air_humidity", "air_temperature", "light_intensity", "soil_moisture"
            )));

    // 修改switch为传统写法
    @Override
    public MetricResponse get24HourMetricData(String metric) {
        validateMetricType(metric);
        switch (metric) {
            case "air_humidity":
                return process24H(metric, "humidity", airHumidityMapper);
            case "air_temperature":
                return process24H(metric, "temperature", airTemperatureMapper);
            case "light_intensity":
                return process24H(metric, "intensity", lightIntensityMapper);
            case "soil_moisture":
                return process24H(metric, "moisture", soilMoistureMapper);
            default:
                throw new IllegalStateException("Unexpected value: " + metric);
        }
    }
    @Override
    public MetricResponse get7DayMetricData(String metric) throws BusinessException {
        validateMetricType(metric);
        switch (metric) {
            case "air_humidity":
                return process7D(metric,"humidity" , airHumidityMapper);
            case "air_temperature":
                return process7D(metric, "temperature", airTemperatureMapper);
            case "light_intensity":
                return process7D(metric, "intensity",lightIntensityMapper);
            case "soil_moisture":
                return process7D(metric, "moisture",soilMoistureMapper);
            default:
                throw new BusinessException("无效的指标类型");
        }
    }


    private final EnvironmentCurrentMapper mapper;

    @Override
    public EnvironmentCurrent getByMetricType(String metricType) {
        if (!VALID_METRICS.contains(metricType)) {
            throw new BusinessException("无效的指标类型: " + metricType);
        }

        EnvironmentCurrent environmentCurrent = mapper.selectOne(new LambdaQueryWrapper<EnvironmentCurrent>()
                .eq(EnvironmentCurrent::getMetricType, metricType));
        if(environmentCurrent == null){
            throw new BusinessException( getFieldName(metricType) + "的值不存在");
        }

        return environmentCurrent;
    }

    @Override
    @Transactional
    public void upsertValue(EnvironmentCurrent entity) {
        if (mapper.updateCurrentValue(entity) == 0) {
            mapper.insert(entity);
        }
    }


    // 通用24小时处理逻辑
    private <T> MetricResponse process24H(String metric, String fieldName, BaseMapper<T> mapper) {
        List<Map<String, Object>> rawData = environmentMetricsMapper.select24HMetricData(metric, fieldName);

        List<DataPoint24H> dataPoints = new ArrayList<>();
        for (Map<String, Object> map : rawData) {
            dataPoints.add(convertTo24HDataPoint(map));
        }
        return new MetricResponse(
                metric,
                getUnit(metric),
                fillMissingTimeSlots(dataPoints)
        );
    }
    // 通用7天处理逻辑
    private <T> MetricResponse process7D(String metric,String fieldName, BaseMapper<T> mapper) {
        List<Map<String, Object>> rawData = environmentMetricsMapper.select7DayMetricData(metric, fieldName);
        List<DataPoint7D> dataPoints = new ArrayList<>();
        for (Map<String, Object> map : rawData) {
            dataPoints.add(convertTo7DDataPoint(map));
        }
        return new MetricResponse(
                metric,
                getUnit(metric),
                fillMissingDates(dataPoints)
        );
    }



    // 字段名映射
    private String getFieldName(String metric) {
        switch (metric) {
            case "air_humidity":
                return "空气湿度";
            case "soil_moisture":
                return "土壤湿度";
            case "light_intensity":
                return "光照强度";
            case "air_temperature":
                return "空气温度";
            default:
                throw new BusinessException("无效的指标类型");
        }
    }

    private String getUnit(String metric) {
        switch (metric) {
            case "air_humidity":
                return "%";
            case "air_temperature":
                return "°C";
            case "light_intensity":
                return "lux";
            case "soil_moisture":
                return "%";
            default:
                return "";
        }
    }

    // 类型校验
    private void validateMetricType(String metric) {
        if (!VALID_METRICS.contains(metric)) {
            throw new BusinessException("无效的指标类型: " + metric);
        }
    }

    // 数据转换方法
    private DataPoint24H convertTo24HDataPoint(Map<String, Object> map) {
        return new DataPoint24H(
                (String) map.get("time"),
                ((Number) map.get("value")).intValue(),
                ((Number) map.get("changeValue")).intValue(),
                ((Number) map.get("changeRate")).floatValue()
        );
    }

    private DataPoint7D convertTo7DDataPoint(Map<String, Object> map) {
        Object rawDate = map.get("date");
        String dateStr = (rawDate instanceof java.sql.Date) ? rawDate.toString() : String.valueOf(rawDate);

        return new DataPoint7D(
                dateStr,
                ((Number) map.getOrDefault("max_value", 0)).intValue(),
                ((Number) map.getOrDefault("avg_value", 0)).doubleValue(),
                ((Number) map.getOrDefault("min_value", 0)).intValue()
        );
    }


    // 补充缺失时间段逻辑（示例实现）
    private List<DataPoint24H> fillMissingTimeSlots(List<DataPoint24H> data) {
// 改造为完整时间点
        List<String> expectedTimes = Arrays.asList(
                "00:00", "02:00", "04:00", "06:00", "08:00", "10:00",
                "12:00", "14:00", "16:00", "18:00", "20:00", "22:00"
        );
        return expectedTimes.stream()
                .map(time -> data.stream()
                        .filter(d -> d.getTime().equals(time))
                        .findFirst()
                        .orElse(new DataPoint24H(time, null, null, null)))
                .collect(Collectors.toList());
    }

    private List<DataPoint7D> fillMissingDates(List<DataPoint7D> existingData) {
        // 生成最近7天的日期列表
        List<String> expectedDates = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        for (int i = 6; i >= 0; i--) {
            expectedDates.add(now.minusDays(i).toLocalDate().toString());
        }

        // 填充缺失数据
        return expectedDates.stream()
                .map(date -> existingData.stream()
                        .filter(d -> d.getDate().equals(date))
                        .findFirst()
                        .orElse(new DataPoint7D(date, null, null, null)))
                .collect(Collectors.toList());
    }

}